package com.derbysoft.dswitch.adapter.ihg.dswitch3.service.handler;

import com.derbysoft.dswitch.adapter.ihg.common.domain.Direction;
import com.derbysoft.dswitch.adapter.ihg.common.domain.OperationType;
import com.derbysoft.dswitch.adapter.ihg.common.domain.ReservationLog;
import com.derbysoft.dswitch.adapter.ihg.common.log.LogBody;
import com.derbysoft.dswitch.adapter.ihg.common.log.LogDetailPair;
import com.derbysoft.dswitch.adapter.ihg.common.log.PerformanceLogger;
import com.derbysoft.dswitch.adapter.ihg.common.log.TransactionLogger;
import com.derbysoft.dswitch.adapter.ihg.common.utils.EnvironmentUtils;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.HotelProviderService;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.service.impl.ElapsedTimeType;
import com.derbysoft.dswitch.dto.common.KeyValue;
import com.derbysoft.dswitch.remote.hotel.dto.HotelCancelRequest;
import com.derbysoft.dswitch.remote.hotel.dto.HotelCancelResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
 * Created by: jason
 * Date: 2012-05-22
 */
@Service("hotelCancelHandler")
public class HotelCancelHandler
        implements RemoteServiceHandler<HotelCancelRequest, HotelCancelResponse> {

    protected HotelProviderService<HotelCancelRequest, HotelCancelResponse> hotelProviderService;

    @Override
    public HotelCancelResponse invoke(HotelCancelRequest request) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        TransactionLogger.getReservationLogger().set(createReservationLog(request));

        HotelCancelResponse response = hotelProviderService.invoke(request);

        stopWatch.stop();

        long elapsedTime = stopWatch.getTotalTimeMillis();
        response.getElapsedTimes().add(new KeyValue(ElapsedTimeType.ADAPTER.name(), String.valueOf(elapsedTime)));

        TransactionLogger.getReservationLogger().get().setTimeSpan(elapsedTime);

        if (EnvironmentUtils.appendDerbyLog()) {
            appendLogDetail(request, response, elapsedTime);
        }

        if (response.getError() != null) {
            TransactionLogger.getReservationLogger().get().setError(true);
            TransactionLogger.getReservationLogger().get().setException(response.getError().getMessage());
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Fail.name());
        } else {
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Success.name());
        }
        return response;
    }

    private void appendLogDetail(HotelCancelRequest request, HotelCancelResponse response, long elapsedTime) {
        Set<LogDetailPair> logDetails = TransactionLogger.getLogDetails().get();
        if (logDetails == null) {
            logDetails = new HashSet<LogDetailPair>();
        }
        logDetails.add(LogDetailPair.build(request, Direction.FROM_CHANNEL));
        logDetails.add(LogDetailPair.build(response, Direction.TO_CHANNEL));
        TransactionLogger.getLogDetails().set(logDetails);
        TransactionLogger.getReservationLogger().get().setTimeSpan(elapsedTime);
    }

    protected ReservationLog createReservationLog(HotelCancelRequest request) {
        ReservationLog reservationLog = new ReservationLog();
        reservationLog.setId(UUID.randomUUID().toString());
        reservationLog.setTaskId(request.getHeader().getTaskId());
        reservationLog.setChannel(request.getHeader().getSource());
        reservationLog.setErsp(request.getHotelCancelRQ().getErsp());
        reservationLog.setOperationType(OperationType.CANCEL_RESERVATION);
        return reservationLog;
    }

    public void setHotelProviderService(HotelProviderService<HotelCancelRequest, HotelCancelResponse> hotelProviderService) {
        this.hotelProviderService = hotelProviderService;
    }
}
